package org.aspectsense.utilitydsl;

import java.util.HashMap;
import java.util.logging.Logger;

import org.antlr.runtime.ANTLRStringStream;
import org.antlr.runtime.CommonTokenStream;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
import org.aspectsense.middleware.annotations.AspectSenseCore;
import org.aspectsense.middleware.interfaces.UtilityParsingService;


@AspectSenseCore()
public class UtilityParsingServiceImpl implements UtilityParsingService  {

	
	private  HashMap <String,CommonTree>input2Tree;
	private  HashMap <String,CommonTokenStream>input2Tokens;
	
	
	private static final Logger logger = Logger.getLogger(org.aspectsense.middleware.interfaces.UtilityParsingService.class.getName());

	public UtilityParsingServiceImpl (){
		
		input2Tree = new HashMap<String, CommonTree>();
		input2Tokens = new HashMap<String, CommonTokenStream>();
	}

	public double calculateUtility(String input) {
		
		CommonTree t;
		CommonTokenStream tok;
		if (input==null || input.compareTo("")==0)
			return 0.0;
		
		//If already exists a tree for the current input
		if (input2Tree.get(input)==null)
		{
			constructTree(input);
			logger.info("New parse tree needed for "+input);
		}
		
		t = input2Tree.get(input);
		tok = input2Tokens.get(input);
		
				
		return walkTree (t,tok);
	}
	
	private  double walkTree (CommonTree t, CommonTokenStream tok){

		double result=0.0;

		// Create a tree node stream from resulting tree
		CommonTreeNodeStream nodes = new CommonTreeNodeStream(t);
		// AST nodes have payloads that point into token stream
		nodes.setTokenStream(tok); 
		UtilTree walker = new UtilTree(nodes); // create a tree parser
		try {
			result=walker.prog();
		} catch (RecognitionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return result;

	}

	private  void constructTree (String in){

		// create a CharStream that reads from String
		ANTLRStringStream input = new ANTLRStringStream(in);
		// Create an ExprLexer that feeds from that stream
		UtilityLexer lexer = new UtilityLexer(input);
		// Create a stream of tokens pulled from the lexer
		CommonTokenStream tokens = new CommonTokenStream(lexer);
		// Create a parser that feeds off the token stream
		UtilityParser parser = new UtilityParser(tokens);
		// Begin parsing at rule prog, get return value structure

		UtilityParser.prog_return r = null;
		try {
			r = parser.prog();
		} catch (RecognitionException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		//System.out.println("tree="+((Tree)r.tree).toStringTree());

		//System.out.print("Parse Tree:");
		CommonTree t = (CommonTree)r.getTree(); 

		input2Tree.put(in, t);
		input2Tokens.put(in, tokens);
	
	}


}
